// ----------------------------------
// RSDK Project: Sonic 2
// Script Description: Ball Cannon Object
// Script Author: Christian Whitehead/Simon Thomley
// Unpacked by Rubberduckycooly's script unpacker
// ----------------------------------

// ========================
// Aliases
// ========================

private alias object.value0 : object.timer
private alias object.value1 : object.tablePos
private alias object.value2 : object.enterFrameTable
private alias object.value3 : object.fireFrameTable
private alias object.value4 : object.rotateFrameTable
private alias object.value5 : object.activePlayers
private alias object.value6 : object.lastCannon

// States
private alias 0 : BALLCANNON_IDLE
private alias 1 : BALLCANNON_ENTERED
private alias 2 : BALLCANNON_ROTATE
private alias 3 : BALLCANNON_FIREPLAYER
private alias 4 : BALLCANNON_EXITED

// Player Aliases
private alias object.state : player.state
private alias object.visible : player.visible
private alias object.xpos : player.xpos
private alias object.ypos : player.ypos
private alias object.xvel : player.xvel
private alias object.yvel : player.yvel
private alias object.speed : player.speed
private alias object.gravity : player.gravity
private alias object.animationSpeed : player.animationSpeed
private alias object.animation : player.animation
private alias object.tileCollisions : player.tileCollisions

private alias object.value1  : player.timer
private alias object.value5  : player.rollAnimationSpeed
private alias object.value17 : debugMode.currentSelection
private alias object.value35 : player.jumpAbilityState


// ========================
// Function Declarations
// ========================

reserve function BallCannon_DebugDraw
reserve function BallCannon_DebugSpawn


// ========================
// Static Values
// ========================

private value BallCannon_startDebugID = 0


// ========================
// Tables
// ========================

// Format for FrameTable entries:
// [object.frame], [object.direction]

private table BallCannon_enterFrameTableU
	0, 0
	1, 0
	2, 0
end table

private table BallCannon_enterFrameTableD
	0, 2
	1, 2
	2, 2
end table

private table BallCannon_enterFrameTableL
	3, 1
	4, 1
	5, 1
end table

private table BallCannon_enterFrameTableR
	3, 0
	4, 0
	5, 0
end table

private table BallCannon_rotateFrameTableL
	6, 7, 8, 9, 10, 11, 12, 13
end table

private table BallCannon_rotateFrameTableR
	13, 12, 11, 10, 9, 8, 7, 6
end table


// ========================
// Function Definitions
// ========================

private function BallCannon_DebugDraw
	temp0 = debugMode[0].currentSelection
	temp0 -= BallCannon_startDebugID
	DrawSprite(temp0)
end function


private function BallCannon_DebugSpawn
	temp0 = debugMode[0].currentSelection
	temp0 -= BallCannon_startDebugID
	CreateTempObject(TypeName[Ball Cannon], temp0, object.xpos, object.ypos)
	object[tempObjectPos].drawOrder 		= 4
	object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableU
	object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableR
	object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableR
	object[tempObjectPos].xvel 				= 0x100000
	object[tempObjectPos].yvel 				= 0
	object[tempObjectPos].lastCannon 		= true

	switch object[tempObjectPos].propertyValue
	case 0
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableU
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableR
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableR
		object[tempObjectPos].xvel 				= 0x100000
		object[tempObjectPos].yvel 				= 0
		break

	case 1
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableR
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableD
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableR
		object[tempObjectPos].xvel 				= 0
		object[tempObjectPos].yvel 				= 0x100000
		break

	case 2
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableD
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableL
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableR
		object[tempObjectPos].xvel 				= -0x100000
		object[tempObjectPos].yvel 				= 0
		break

	case 3
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableL
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableU
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableR
		object[tempObjectPos].xvel 				= 0
		object[tempObjectPos].yvel 				= -0x100000
		break

	case 4
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableR
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableU
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableL
		object[tempObjectPos].xvel 				= 0
		object[tempObjectPos].yvel 				= -0x100000
		break

	case 5
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableD
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableR
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableL
		object[tempObjectPos].xvel 				= 0x100000
		object[tempObjectPos].yvel 				= 0
		break

	case 6
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableL
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableD
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableL
		object[tempObjectPos].xvel 				= 0
		object[tempObjectPos].yvel 				= 0x100000
		break

	case 7
		object[tempObjectPos].enterFrameTable 	= BallCannon_enterFrameTableU
		object[tempObjectPos].fireFrameTable 	= BallCannon_enterFrameTableL
		object[tempObjectPos].rotateFrameTable 	= BallCannon_rotateFrameTableL
		object[tempObjectPos].xvel 				= -0x100000
		object[tempObjectPos].yvel 				= 0
		break
		
	end switch
end function


// ========================
// Events
// ========================

event ObjectUpdate
	switch object.state
	case BALLCANNON_ENTERED
		if object.timer == 0
			if object.tablePos == 6
				object.tablePos = 0
				object.timer = 3
				object.state++
			else
				GetTableValue(object.frame, object.tablePos, object.enterFrameTable)
				object.tablePos++
				GetTableValue(object.direction, object.tablePos, object.enterFrameTable)
				object.tablePos++
			end if
		end if
		object.timer++
		object.timer &= 3
		break

	case BALLCANNON_ROTATE
		if object.timer == 0
			if object.tablePos == 8
				object.tablePos = 5
				object.timer = 1
				object.state++
			else
				GetTableValue(object.frame, object.tablePos, object.rotateFrameTable)
				object.direction = FLIP_NONE
				object.tablePos++
			end if
		end if
		object.timer++
		object.timer &= 1
		break

	case BALLCANNON_FIREPLAYER
		if object.timer == 0
			if object.tablePos < 0
				object.tablePos = 0
				object.state++
				foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
					temp0 = 1
					temp0 <<= currentPlayer
					temp0 &= object.activePlayers
					if temp0 != 0
						if object.lastCannon == true
							player[currentPlayer].state 		 	= Player_State_Air
							player[currentPlayer].gravity 		 	= 1
							player[currentPlayer].jumpAbilityState	= 0
							player[currentPlayer].tileCollisions 	= true
						end if
						player[currentPlayer].visible = true
						player[currentPlayer].timer = 0
						player[currentPlayer].speed = object.xvel
						player[currentPlayer].xvel = object.xvel
						player[currentPlayer].yvel = object.yvel
					end if
				next
			else
				GetTableValue(object.direction, object.tablePos, object.fireFrameTable)
				object.tablePos--
				GetTableValue(object.frame, object.tablePos, object.fireFrameTable)
				object.tablePos--
			end if
		end if
		object.timer++
		object.timer &= 3
		break

	case BALLCANNON_EXITED
		object.timer++
		if object.timer == 16
			object.timer = 0
			object.activePlayers = 0
			object.state = BALLCANNON_IDLE
		end if
		break
		
	end switch

	foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
		BoxCollisionTest(C_TOUCH, object.entityPos, -4, -4, 4, 4, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
		if checkResult == true
			temp0 = true
			temp0 <<= currentPlayer
			temp0 &= object.activePlayers
			if temp0 == 0
				player[currentPlayer].state = Player_State_Static
				player[currentPlayer].animation = ANI_JUMPING
				player[currentPlayer].animationSpeed = 0xF0
				player[currentPlayer].rollAnimationSpeed = 0xF0
				player[currentPlayer].xpos = object.xpos
				player[currentPlayer].ypos = object.ypos
				player[currentPlayer].speed = 0
				player[currentPlayer].xvel = 0
				player[currentPlayer].yvel = 0
				player[currentPlayer].visible = false
				player[currentPlayer].tileCollisions = false
				temp0 = true
				temp0 <<= currentPlayer
				object.activePlayers |= temp0
				object.timer = 0
				object.tablePos = 0
				object.state = BALLCANNON_ENTERED
				if object.priority != PRIORITY_XBOUNDS_DESTROY
					object.priority = PRIORITY_ACTIVE
				end if
				PlaySfx(SfxName[Rolling], false)
			end if
		end if
	next

	if object.outOfBounds == true
		if object.priority != PRIORITY_XBOUNDS_DESTROY
			object.priority = PRIORITY_BOUNDS
			object.tablePos = 0
			object.activePlayers = 0
			object.timer = 0
			GetTableValue(object.frame, 0, object.enterFrameTable)
			GetTableValue(object.direction, 1, object.enterFrameTable)
			object.state = BALLCANNON_IDLE
		end if
	end if
end event


event ObjectDraw
	DrawSpriteFX(object.frame, FX_FLIP, object.xpos, object.ypos)
end event


event ObjectStartup
	CheckCurrentStageFolder("Zone07")
	if checkResult == true
		LoadSpriteSheet("OOZ/Objects.gif")
		SpriteFrame(-24, -40, 48, 64, 133, 142)	// Enter Frame 1 (V) - #0
		SpriteFrame(-24, -32, 48, 56, 133, 85)	// Enter Frame 2 (V) - #1
		SpriteFrame(-24, -24, 48, 48, 133, 93)	// Enter Frame 3 (V) - #2
		SpriteFrame(-24, -24, 64, 48, 1, 101)	// Enter Frame 1 (H) - #3
		SpriteFrame(-24, -24, 56, 48, 1, 150)	// Enter Frame 2 (H) - #4
		SpriteFrame(-24, -24, 48, 48, 1, 150)	// Enter Frame 3 (H) - #5
		SpriteFrame(-24, -24, 48, 48, 316, 1) 	// Rotate Frame 1 	 - #6
		SpriteFrame(-24, -24, 48, 48, 365, 1) 	// Rotate Frame 2 	 - #7
		SpriteFrame(-24, -24, 48, 48, 414, 1) 	// Rotate Frame 3 	 - #8
		SpriteFrame(-24, -24, 48, 48, 463, 1) 	// Rotate Frame 4 	 - #9
		SpriteFrame(-24, -24, 48, 48, 316, 50)	// Rotate Frame 5 	 - #10
		SpriteFrame(-24, -24, 48, 48, 365, 50)	// Rotate Frame 6 	 - #11
		SpriteFrame(-24, -24, 48, 48, 414, 50)	// Rotate Frame 7 	 - #12
		SpriteFrame(-24, -24, 48, 48, 463, 50)	// Rotate Frame 8 	 - #13
	else
		LoadSpriteSheet("MBZ/Objects.gif")
		SpriteFrame(-24, -40, 48, 64, 813, 861)	// Enter Frame 1 (V) - #0
		SpriteFrame(-24, -32, 48, 56, 764, 869)	// Enter Frame 2 (V) - #1
		SpriteFrame(-24, -24, 48, 48, 764, 877)	// Enter Frame 3 (V) - #2
		SpriteFrame(-24, -24, 64, 48, 763, 926)	// Enter Frame 1 (H) - #3
		SpriteFrame(-24, -24, 56, 48, 771, 975)	// Enter Frame 2 (H) - #4
		SpriteFrame(-24, -24, 48, 48, 771, 975)	// Enter Frame 3 (H) - #5
		SpriteFrame(-24, -24, 48, 48, 828, 926)	// Rotate Frame 1 	 - #6
		SpriteFrame(-24, -24, 48, 48, 877, 926)	// Rotate Frame 2 	 - #7
		SpriteFrame(-24, -24, 48, 48, 926, 926)	// Rotate Frame 3 	 - #8
		SpriteFrame(-24, -24, 48, 48, 975, 926)	// Rotate Frame 4 	 - #9
		SpriteFrame(-24, -24, 48, 48, 828, 975)	// Rotate Frame 5 	 - #10
		SpriteFrame(-24, -24, 48, 48, 877, 975)	// Rotate Frame 6 	 - #11
		SpriteFrame(-24, -24, 48, 48, 926, 975)	// Rotate Frame 7 	 - #12
		SpriteFrame(-24, -24, 48, 48, 975, 975)	// Rotate Frame 8 	 - #13
	end if

	foreach (TypeName[Ball Cannon], arrayPos0, ALL_ENTITIES)
		if object[arrayPos0].propertyValue > 7
			object[arrayPos0].lastCannon = true
			object[arrayPos0].propertyValue &= 7
		end if

		switch object[arrayPos0].propertyValue
		case 0
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableU
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableR
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableR
			object[arrayPos0].xvel = 0x100000
			object[arrayPos0].yvel = 0
			break

		case 1
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableR
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableD
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableR
			object[arrayPos0].xvel = 0
			object[arrayPos0].yvel = 0x100000
			break

		case 2
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableD
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableL
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableR
			object[arrayPos0].xvel = -0x100000
			object[arrayPos0].yvel = 0
			break

		case 3
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableL
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableU
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableR
			object[arrayPos0].xvel = 0
			object[arrayPos0].yvel = -0x100000
			break

		case 4
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableR
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableU
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableL
			object[arrayPos0].xvel = 0
			object[arrayPos0].yvel = -0x100000
			break

		case 5
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableD
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableR
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableL
			object[arrayPos0].xvel = 0x100000
			object[arrayPos0].yvel = 0
			break

		case 6
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableL
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableD
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableL
			object[arrayPos0].xvel = 0
			object[arrayPos0].yvel = 0x100000
			break

		case 7
			object[arrayPos0].enterFrameTable = BallCannon_enterFrameTableU
			object[arrayPos0].fireFrameTable = BallCannon_enterFrameTableL
			object[arrayPos0].rotateFrameTable = BallCannon_rotateFrameTableL
			object[arrayPos0].xvel = -0x100000
			object[arrayPos0].yvel = 0
			break
			
		end switch

		object[arrayPos0].drawOrder = 4
		object[arrayPos0].propertyValue = 0
		GetTableValue(object[arrayPos0].frame, 0, object[arrayPos0].enterFrameTable)
		GetTableValue(object[arrayPos0].direction, 1, object[arrayPos0].enterFrameTable)
	next

	temp0 = 0
	BallCannon_startDebugID = DebugMode_ObjCount
	while temp0 < 4
		SetTableValue(TypeName[Ball Cannon], DebugMode_ObjCount, DebugMode_TypesTable)
		SetTableValue(BallCannon_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
		SetTableValue(BallCannon_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
		DebugMode_ObjCount++
		temp0++
	loop
end event


// ========================
// Editor Events
// ========================

event RSDKEdit
	if editor.returnVariable == true
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			checkResult = object.propertyValue
			break
			
		case 0 // type
			checkResult = object.propertyValue
			checkResult &= 7
			break
			
		case 1 // noControlLock
			GetBit(checkResult, object.propertyValue, 3)
			break
			
		end switch
	else
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			object.propertyValue = editor.variableValue
			break
			
		case 0 // type
			editor.variableValue &= 7
			object.propertyValue &= 0xF8

			object.propertyValue |= editor.variableValue
			break
			
		case 1 // noControlLock
			CheckNotEqual(editor.variableValue, false)
			SetBit(object.propertyValue, 3, checkResult)
			break
			
		end switch
	end if
end event


event RSDKDraw
	temp0 = object.propertyValue
	temp0 &= 7

	switch temp0
	case 0
		object.enterFrameTable 	= BallCannon_enterFrameTableU
		object.fireFrameTable 	= BallCannon_enterFrameTableR
		break

	case 1
		object.enterFrameTable 	= BallCannon_enterFrameTableR
		object.fireFrameTable 	= BallCannon_enterFrameTableD
		break

	case 2
		object.enterFrameTable 	= BallCannon_enterFrameTableD
		object.fireFrameTable 	= BallCannon_enterFrameTableL
		break

	case 3
		object.enterFrameTable 	= BallCannon_enterFrameTableL
		object.fireFrameTable 	= BallCannon_enterFrameTableU
		break

	case 4
		object.enterFrameTable 	= BallCannon_enterFrameTableR
		object.fireFrameTable 	= BallCannon_enterFrameTableU
		break

	case 5
		object.enterFrameTable 	= BallCannon_enterFrameTableD
		object.fireFrameTable 	= BallCannon_enterFrameTableR
		break

	case 6
		object.enterFrameTable 	= BallCannon_enterFrameTableL
		object.fireFrameTable 	= BallCannon_enterFrameTableD
		break

	case 7
		object.enterFrameTable 	= BallCannon_enterFrameTableU
		object.fireFrameTable 	= BallCannon_enterFrameTableL
		break
		
	end switch
	
	GetTableValue(object.frame, 0, object.enterFrameTable)
	GetTableValue(object.direction, 1, object.enterFrameTable)

	DrawSpriteFX(object.frame, FX_FLIP, object.xpos, object.ypos)
end event


event RSDKLoad
	CheckCurrentStageFolder("Zone07")
	if checkResult == true
		LoadSpriteSheet("OOZ/Objects.gif")
		SpriteFrame(-24, -40, 48, 64, 133, 142)	// Enter Frame 1 (V) - #0
		SpriteFrame(-24, -32, 48, 56, 133, 85)	// Enter Frame 2 (V) - #1
		SpriteFrame(-24, -24, 48, 48, 133, 93)	// Enter Frame 3 (V) - #2
		SpriteFrame(-24, -24, 64, 48, 1, 101)	// Enter Frame 1 (H) - #3
		SpriteFrame(-24, -24, 56, 48, 1, 150)	// Enter Frame 2 (H) - #4
		SpriteFrame(-24, -24, 48, 48, 1, 150)	// Enter Frame 3 (H) - #5
		SpriteFrame(-24, -24, 48, 48, 316, 1) 	// Rotate Frame 1 	 - #6
		SpriteFrame(-24, -24, 48, 48, 365, 1) 	// Rotate Frame 2 	 - #7
		SpriteFrame(-24, -24, 48, 48, 414, 1) 	// Rotate Frame 3 	 - #8
		SpriteFrame(-24, -24, 48, 48, 463, 1) 	// Rotate Frame 4 	 - #9
		SpriteFrame(-24, -24, 48, 48, 316, 50)	// Rotate Frame 5 	 - #10
		SpriteFrame(-24, -24, 48, 48, 365, 50)	// Rotate Frame 6 	 - #11
		SpriteFrame(-24, -24, 48, 48, 414, 50)	// Rotate Frame 7 	 - #12
		SpriteFrame(-24, -24, 48, 48, 463, 50)	// Rotate Frame 8 	 - #13
	else
		LoadSpriteSheet("MBZ/Objects.gif")
		SpriteFrame(-24, -40, 48, 64, 813, 861)	// Enter Frame 1 (V) - #0
		SpriteFrame(-24, -32, 48, 56, 764, 869)	// Enter Frame 2 (V) - #1
		SpriteFrame(-24, -24, 48, 48, 764, 877)	// Enter Frame 3 (V) - #2
		SpriteFrame(-24, -24, 64, 48, 763, 926)	// Enter Frame 1 (H) - #3
		SpriteFrame(-24, -24, 56, 48, 771, 975)	// Enter Frame 2 (H) - #4
		SpriteFrame(-24, -24, 48, 48, 771, 975)	// Enter Frame 3 (H) - #5
		SpriteFrame(-24, -24, 48, 48, 828, 926)	// Rotate Frame 1 	 - #6
		SpriteFrame(-24, -24, 48, 48, 877, 926)	// Rotate Frame 2 	 - #7
		SpriteFrame(-24, -24, 48, 48, 926, 926)	// Rotate Frame 3 	 - #8
		SpriteFrame(-24, -24, 48, 48, 975, 926)	// Rotate Frame 4 	 - #9
		SpriteFrame(-24, -24, 48, 48, 828, 975)	// Rotate Frame 5 	 - #10
		SpriteFrame(-24, -24, 48, 48, 877, 975)	// Rotate Frame 6 	 - #11
		SpriteFrame(-24, -24, 48, 48, 926, 975)	// Rotate Frame 7 	 - #12
		SpriteFrame(-24, -24, 48, 48, 975, 975)	// Rotate Frame 8 	 - #13
	end if

	AddEditorVariable("type")
	SetActiveVariable("type")
	AddEnumVariable("Up -> Right", 0)
	AddEnumVariable("Right -> Down", 1)
	AddEnumVariable("Down -> Left", 2)
	AddEnumVariable("Left -> Up", 3)
	AddEnumVariable("Right -> Up", 4)
	AddEnumVariable("Down -> Right", 5)
	AddEnumVariable("Left -> Down", 6)
	AddEnumVariable("Up -> Left", 7)

	AddEditorVariable("noControlLock")
	SetActiveVariable("noControlLock")
	AddEnumVariable("false", false)
	AddEnumVariable("true", true)
end event
